In this lesson, you learned about the advanced features of Visual C++. You learned how to make one class out of another and how to change the way a function is called to depend on either the calling type or the object type.
In this lesson, you saw the following:
Project 11 Listing. An object-oriented pet care program.
1:// File name : PROJCT11.CPP
2:// Object oriented pet program to manage
3:// a simple list of different types of
4:// pets
5://
6:#include <iostream.h>
7:#include <string.h>
8:
9://------------------------------------------------------------
10:// Pet class
11://
12:class Pet
13: {
14: public:
15: virtual ~Pet() // Destructor
16: {
17: delete [] name;
18: }
19: void Print() const; // Print all about pet
20: void Query(); // Get details
21: const char * GetName() const// Provide name string
22: {
23: if (name)
24: return name;
25: else
26: return "";
27: }
28: protected:
29: virtual void PrintDetails() const = 0;// Print details
30: virtual void QueryDetails() = 0; // Ask for details
31: virtual const char * GetPetType() const = 0;
32: Pet() // protected -
33: // do not make Pets
34: {
35: name = 0;
36: }
37: private:
38: char * name;
39: };
40:void Pet::Print() const
41: {
42: cout << GetPetType() << " : ";
43: if (name)
44: cout << name << " - ";
45: PrintDetails();
46: cout << endl;
47: }
48:
49:void Pet::Query()
50: {
51: char tempName[81];
52: cout << "What is your pet " << GetPetType() <<"'s name? ";
53: cin.getline(tempName,81);
54: if (name)
55: delete [] name;
56: name = new char[strlen(tempName) + 1];
57: strcpy(name,tempName);
58: QueryDetails();
59: }
60:
61://------------------------------------------------------------
62:// Cat class - derived from Pet
63://
64:class Cat : public Pet
65: {
66: public:
67: Cat(int Scratches = 1)
68: {
69: scratches = Scratches;
70: }
71: protected:
72: virtual void PrintDetails() const;
73: virtual void QueryDetails();
74: const char * GetPetType() const
75: {
76: return "Cat";
77: }
78: private:
79: int scratches;
80: };
81:
82:void Cat::PrintDetails() const
83: {
84: cout << "Scratches: " << (scratches? "Yes":"No");
85: }
86:
87:void Cat::QueryDetails()
88: {
89: char yn;
90: cout << "Does your cat " << GetName() << " scratch? ";
91: cin >> yn;
92: cin.ignore(80,'\n');
93: if (yn == 'Y' || yn == 'y')
94: scratches = 1;
95: else
96: scratches = 0;
97: }
98:
99://------------------------------------------------------------
100:// Dog class - derived from Pet
101://
102:
103:class Dog : public Pet
104: {
105: public:
106: Dog(int Barks = 1)
107: {
108: barks = Barks;
109: }
110: protected:
111: virtual void PrintDetails() const;
112: virtual void QueryDetails();
113: const char * GetPetType() const
114: {
115: return "Dog";
116: }
117: private:
118: int barks;
119: };
120:
121:void Dog::PrintDetails() const
122: {
123: cout << "Barks: " << (barks? "Yes":"No");
124: }
125:
126:void Dog::QueryDetails()
127: {
128: char yn;
129: cout << "Does your dog " << GetName() << " bark? ";
130: cin >> yn;
131: cin.ignore(80,'\n');
132: if (yn == 'Y' || yn == 'y')
133: barks = 1;
134: else
135: barks = 0;
136: }
137:
138://------------------------------------------------------------
139:// Fish class - derived from Pet
140://
141:class Fish : public Pet
142: {
143: public:
144: Fish(int ColdWater = 0)
145: {
146: coldWater = ColdWater;
147: }
148: protected:
149: virtual void PrintDetails() const;
150: virtual void QueryDetails();
151: const char * GetPetType() const
152: {
153: return "Fish";
154: }
155: private:
156: int coldWater;
157: };
158:void Fish::PrintDetails() const
159: {
160: cout << (coldWater? "Cold water":"Tropical");
161: }
162:
163:void Fish::QueryDetails()
164: {
165: char yn;
166: cout << "Is your fish " << GetName() << " tropical? ";
167: cin >> yn;
168: cin.ignore(80,'\n');
169: if (yn == 'Y' || yn == 'y')
170: coldWater = 0;
171: else
172: coldWater = 1;
173: }
174:
175://------------------------------------------------------------
176:// main procedure
177://
178:
179:void main()
180: {
181: const int maxPets = 20;
182: char type = ' ';
183: Pet * pets[maxPets] = {0};
184: int count = 0;
185:
186: while (count < maxPets)
187: {
188: // Where do you want to go today?
189: cout << "Pet type, [C]at, [D]og, [F]ish, [Q]uit: ";
190: cin >> type;
191: cin.ignore(80,'\n');
192:
193: // Stop loop early
194: if (type == 'q' || type == 'Q')
195: break;
196:
197: switch (type)
198: {
199: case 'C': // Cat
200: case 'c':
201: {
202: pets[count] = new Cat;
203: break;
204: }
205: case 'D': // Dog
206: case 'd':
207: {
208: pets[count] = new Dog;
209: break;
210: }
211: case 'F': // Fish
212: case 'f':
213: {
214: pets[count] = new Fish;
215: break;
216: }
217: default:
218: continue; // can be used in switch
219: }
220: pets[count]->Query();
221: count++;
222: }
223:
224: // List pets - don't need derived classes for this
225: cout << endl << "Pet Names" << endl;
226: for (int i = 0; i < count; i++)
227: {
228: cout << pets[i]->GetName();
229: cout << endl;
230: }
231:
232: // Print characteristics - rely on virtual functions
233: cout << endl << "Characteristics" << endl;
234: for (i = 0; i < count; i++)
235: pets[i]->Print();
236:
237: // Tidy up storage
238: for (i = 0; i < count; i++)
239: delete pets[i];
240: }
OUTPUT
Pet type, [C]at, [D]og, [F]ish, [Q]uit: cat What is your pet Cat's name? Tibbles Does your cat Tibbles scratch? no, never has Pet type, [C]at, [D]og, [F]ish, [Q]uit: d What is your pet Dog's name? Ross Does your dog Ross bark? Yes Pet type, [C]at, [D]og, [F]ish, [Q]uit: f What is your pet Fish's name? Wanda Is your fish Wanda tropical? yes Pet type, [C]at, [D]og, [F]ish, [Q]uit: p Pet type, [C]at, [D]og, [F]ish, [Q]uit: q Pet Names Tibbles Ross Wanda Characteristics Cat : Tibbles - Scratches: No Dog : Ross - Barks: Yes Fish : Wanda - Tropical
Description
1: Comment refers to the source filename.
2: Comment to describe the program.
3: The program description continues.
4: The program description continues.
5: Blank lines help to make the program more readable.
6: Include the header for the library of stream output functions.
7: Include the header for the library of string handling functions.
8: Blank lines help to make the program more readable.
9: A comment helps separate the different classes.
10: A title for the following class.
11: A blank comment can also be used for appearance.
12: A line to declare a class called Pet.
13: All classes start with an opening brace.
14: All members after this label will be declared public.
15: The destructor for Pet is shown with the ~ character. It is declared virtual.
16: The destructor function is coded inline. The function starts with an opening brace.
17: Delete the character string pointed to by name.
18: All functions end with a closing brace.
19: A function Print() is declared that will not change the class members.
20: A function Query() is declared. This is allowed to change class members.
21: A function GetName() is declared that will not change class members.
22: All functions start with opening braces. This is declared inline.
23: name might not have a string attached, but the constructor ensures it is zeroed.
24: If name did have a string, return it.
25: A single statement if-else does not need braces surrounding the statement.
26: Return a blank string if no name has been set.
27: A closing brace ends all functions.
28: All members following this label will be protected.
29: This virtual function has not been defined and is known as a pure virtual function.
30: QueryDetails() is also a pure virtual function.
31: There is no definition for GetPetType().
32: The default constructor for the Pet class.
33: A comment helps explain an unusual coding feature.
34: An inline function starts with a closing brace.
35: Pointers should always be initialized. A valid pointer can never be zero.
36: Functions always end with closing braces.
37: All members following this label will be private.
38: A pointer to a character string initially does not own any storage.
39: All class declarations end with both a closing brace and a semicolon.
40: The function Print() belonging to the Pet class is defined.
41: All functions start with an opening brace.
42: Output the type of pet, using a virtual function so that each class can output its name.
43: Check the validity of a character pointer before using.
44: name is a member of this class, so it needs no special function to access it.
45: Call a virtual function to get details that differ by derived type.
46: Output a newline sequence.
47: All functions end with a closing brace.
48: Blank lines help you make the code more readable.
49: Define the nonvirtual function Query.
50: All functions start with an opening brace.
51: Declare a temporary character string much bigger than expected input.
52: Ask for user input, using a virtual function to customize the request for each class.
53: Get the name into a temporary string.
54: If the name already points at a string, delete it.
55: Delete the current string to recover the memory.
56: Create a dynamic memory allocation just big enough to hold the string and its terminator.
57: Copy the temporary name into the class storage.
58: Call a virtual function to get details specific to the actual class.
59: All functions end with a closing brace.
60: Blank lines help to make the program more readable.
61: A comment to mark the start of a new class.
62: A comment to identify which class is now being defined.
63: Empty comments can enhance the appearance of the program.
64: Class Cat builds the functionality of class Pet.
65: Class definitions start with an opening brace.
66: All members following this label will be public.
67: The constructor for cat can optionally take a parameter.
68: A function always starts with an opening brace.
69: A constructor should always initialize the members.
70: A function always ends with a closing brace.
71: All the functions following this label will be protected.
72: This class is going to define the PrintDetails() function.
73: This class is going to define the QueryDetails() function.
74: This class defines the GetPetType() function.
75: All functions start with an opening brace.
76: This function returns the literal string Cat.
77: All functions end with a closing brace.
78: All members following this label will be private.
79: A private data member that is an integer.
80: All class definitions end with a closing brace and a semicolon.
81: Blank lines make the program more readable.
82: Define the function PrintDetails(). This version belongs to Cat.
83: All functions start with an opening brace.
84: Output extra details of Cat class.
85: All functions end with a closing brace.
86: Blank lines help to make the program more readable.
87: Define the function QueryDetails().
88: All functions start with an opening brace.
89: Declare a character variable to test the input.
90: Query the user for information. Customize the output with a call for base class information.
91: Ask for an answer that takes just the first character.
92: Ignore the input up until the newline character.
93: If the answer is yes. . .
94: Set the member flag to true.
95: If the answer is no. . .
96: Set the member flag to false.
97: All functions end with a closing brace.
98: Blank lines help to make the program more readable.
99: A comment to mark the start of a new class.
100: A comment to identify which class is now being defined.
101: Empty comments can enhance the appearance of the program.
102: Blank lines help to make the program more readable.
103: Class Dog builds the functionality of class Pet.
104: Class definitions start with an opening brace.
105: All members following this label will be public.
106: The constructor for Dog can optionally take a parameter.
107: A function always starts with an opening brace.
108: A constructor should always initialize the members.
109: A function always ends with a closing brace.
110: All functions following this label will be protected.
111: This class is going to define the PrintDetails() function.
112: This class is going to define the QueryDetails() function.
113: This class defines the GetPetType() function.
114: All functions start with an opening brace.
115: This function returns the literal string Dog.
116: All functions end with a closing brace.
117: All members following this label will be private.
118: A private data member that is an integer.
119: All class definitions end with a closing brace and a semicolon.
120: Blank lines make the program more readable.
121: Define the function PrintDetails(). This version belongs to Cat.
122: All functions start with an opening brace.
123: Output extra details of Dog class.
124: All functions end with a closing brace.
125: Blank lines help to make the program more readable.
126: Define the function QueryDetails().
127: All functions start with an opening brace.
128: Declare a character variable to test the input.
129: Query the user for information. Customize the output with a call for base class information.
130: Ask for an answer that takes just the first character.
131: Ignore the input up until the newline character.
132: If the answer is yes. . .
133: Set the member flag to true.
134: If the answer is no. . .
135: Set the member flag to false.
136: All functions end with a closing brace.
137: Blank lines help to make the program more readable.
138: A comment to mark the start of a new class.
139: A comment to identify which class is now being defined.
140: Empty comments can enhance the appearance of the program.
141: Class Fish builds the functionality of class Pet.
142: Class definitions start with an opening brace.
143: All members following this label will be public.
144: The constructor for Fish can optionally take a parameter.
145: A function always starts with an opening brace.
146: A constructor should always initialize the members.
147: A function always ends with a closing brace.
148: All the functions following this label will be protected.
149: This class is going to define the PrintDetails() function.
150: This class is going to define the QueryDetails() function.
151: This class defines the GetPetType() function.
152: All functions start with an opening brace.
153: This function returns the literal string Fish.
154: All functions end with a closing brace.
155: All members following this label will be private.
156: A private data member that is an integer.
157: All class definitions end with a closing brace and a semicolon.
158: Define the function PrintDetails(). This version belongs to Fish.
159: All functions start with an opening brace.
160: Output extra details of Cat class.
161: All functions end with a closing brace.
162: Blank lines help to make the program more readable.
163: Define the function QueryDetails().
164: All functions start with an opening brace.
165: Declare a character variable to test the input.
166: Query the user for information. Customize the output with a call for base class information.
167: Ask for an answer that takes just the first character.
168: Ignore the input up until the newline character.
169: If the answer is yes. . .
170: Set the member flag to true.
171: If the answer is no. . .
172: Set the member flag to false.
173: All functions end with a closing brace.
174: Blank lines make the program more readable.
175: A comment to divide the code.
176: A comment to tell the programmer that he has found the main procedure.
177: Blank comments can enhance the appearance of the program.
178: Blank lines make the program more readable.
179: The start of the main procedure.
180: All functions start with an opening brace.
181: Define a constant for the maximum number of entries.
182: Initialize a temporary input character.
183: Define an array of pointers to the Pet class.
184: A counter to record how many pets have been entered.
185: Blank lines make the program more readable.
186: Do the following statements as long as the number of entries do not exceed the array capacity.
187: A while loop of multiple statements is delimited by an opening brace.
188: Not all comments serve a useful purpose.
189: Prompt the user for a selection.
190: Store the first character of a users answer.
191: Ignore any spare input after the first character.
192: Blank lines make the program more readable.
193: Comments can explain why code is written.
194: Test the input to see whether the user has finished.
195: Leave the loop if the if test is true.
196: Blank lines make the program more readable.
197: Avoid complex if statements by using the switch statement.
198: switch statements are enclosed in braces.
199: Execute from here if type is 'C'.
200: Execute from here if type is 'c'. The first case will fall through.
201: case statements can be enclosed in a block.
202: Make an object of type Cat and store it in a general Pet pointer.
203: Break out of the rest of the switch statement.
204: End of case block.
205: case for Dog.
206: case for Dog.
207: case statements can be enclosed in a block.
208: Make an object of type Dog and store it in a general Pet pointer.
209: Break out of the rest of the switch statement.
210: End of case block.
211: case for Fish
212: case for Fish
213: case statements can be enclosed in a block.
214: Make an object of type Fish and store it in a general Pet pointer.
215: Break out of the rest of the switch statement.
216: End of case block.
217: If the input does not match any planned case, do the following.
218: Executing continue will go around the loop, skipping the remaining code.
219: End the switch statement.
220: Call the input function for the new object. Because it contains virtual function calls, different code for each type will be called.
221: Increment the number of valid objects count.
222: End the while loop compound statement.
223: Blank lines help make the program more readable.
224: Comment to help understand the following processing.
225: Output a title.
226: for as many items in the container.
227: for loops performing multiple statements enclose them in braces.
228: Output the pet's name by using a nonvirtual function belonging to the base class.
229: A newline character sequence is output.
230: End of the for loop is denoted by the closing brace.
231: Blank lines make the program more readable.
232: A comment to explain the following processing.
233: Output a title.
234: for all the items in the container.
235: A for loop can execute a single statement.
236: Blank lines make the code more readable.
237: A comment to explain the following processing.
238: for each item in the container.
239: Delete the storage associated with the pointer.
240: The main function ends with a closing brace.
29: Classes containing pure virtual functions are known as abstract classes.
69: If no base constructor is explicitly called in the initialization list, the default base constructor is called.
71: Protected members are only visible to this class and derived classes.
76: Visual C++ can't access the actual class name.
183: An array of pointers takes up a small amount of space compared to the classes, and derived classes might take up much more storage than a base class.
201: case statements must be enclosed in braces if they declare a variable.
203: Meeting a case statement does not cause a branch out of the switch statement.
226: The scope of local variable i is the block containing for, not the for loop itself. Note the following for loops.
235: Print() contains virtual functions that will execute code specific to each object's class.
239: Because the base class destructor is virtual, the correct destructor will be called even though the pointer belongs to the base class.